import logging
from copy import deepcopy

from django.http import JsonResponse, Http404
from django.shortcuts import render, redirect
from django.urls import reverse_lazy
from django.views.generic import TemplateView, CreateView
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin

from supervisor_dj.tasks import write_msg_to_log_and_db_task, supervisor_processlist_status_update_task
from .utils_v4 import Supervisor_Process_Managet_Class   as s_p_m_class, Supervisor_Process_Managet_Class

from .models import SupervisorHost, Supervisor_Process, Supervisor_Action_History

from .apps import SupervisorDjConfig

app_name = SupervisorDjConfig.name

logger = logging.getLogger()


class Supervisor_Search_Mixin:
    def get_queryset(self, model):
        q = self.request.GET.get('q')
        if q:
            return model.objects.filter(processes__name__contains=q).select_related()
        return model.objects.all().select_related()


class supervisor_hostlist_class_view(LoginRequiredMixin, Supervisor_Search_Mixin, TemplateView):
    template_name = 'supervisor_dj/supervisor_dj_list_v2.html'

    def get_context_data(self, **kwargs):
        self.request.app_name = app_name

        action_histtory = Supervisor_Action_History.objects.all()[:5]
        host_count = SupervisorHost.objects.count()
        process_count = Supervisor_Process.objects.count()
        data = {
            "action_histtory": action_histtory,
            "host_count": host_count,
            "process_count": process_count,
            "app_name": app_name,
        }
        q = self.request.GET.get('q')

        if q:
            # 是否有搜索内容
            data['processes_list'] = Supervisor_Process.objects.filter(name__contains=q)
            data['q'] = q
        else:
            data['process_host_list'] = SupervisorHost.objects.all()
        kwargs.update(data)
        return super().get_context_data(**kwargs)


@login_required
def action(request):
    """
    启动,停止,重启进程
        :param request:   ip process_name action
        :return:
    """
    can_do_action = ["start", "stop", "restart"]

    # 参数方法判断
    process_name = request.GET.get('process_name', None)
    ip = request.GET.get('ip', None)
    action = request.GET.get('action', None)

    if not ip or not action or not process_name:
        data = {"status_code": False, "msg": "必须传入process_name,ip,action参数"}
        return JsonResponse(data)
    if not action in can_do_action:
        data = {"status_code": False, "msg": f"{action}方法不被允许"}
        return JsonResponse(data)

    # api操作
    res_msg = s_p_m_class().action(process_name=process_name, ip=ip, action_method=action)

    if res_msg['msg']['status_code'] == True:
        process_info_list = res_msg["process_status_data"]
        supervisor_processlist_status_update_task(ip=ip, process_list=process_info_list["data"])

    req_user = request.user.user_name
    w_2_log = res_msg["msg"]
    w_2_log["user"] = req_user
    # 记录日志
    write_msg_to_log_and_db_task(**w_2_log)

    return JsonResponse(w_2_log, )


@login_required
def get_process_info_detail_view(request):
    """
    获取进程详情
        :param request:
        :return:
    """
    can_do_action = ["getone"]

    # 参数方法判断
    process_name = request.GET.get('process_name', None)
    ip = request.GET.get('ip', None)
    action = request.GET.get('action', None)

    if not ip or not action or not process_name:
        data = {"status_code": False, "msg": "必须传入process_name,ip,action参数"}
        return JsonResponse(data)
    if not action in can_do_action:
        data = {"status_code": False, "msg": f"{action}方法不被允许"}
        return JsonResponse(data)

    # 判断数据库中是否存在此对象
    super_model_obj = Supervisor_Process.objects.filter(ip=ip, name=process_name)
    if not super_model_obj.exists():
        data = {"status_code": False, "msg": f"获取详情失败,{ip}-{process_name}对象不存在"}
        return JsonResponse(data)
    # 删除
    super_model_obj.delete()

    # 通过api获取信息
    process_info_list = Supervisor_Process_Managet_Class().get_process_info_list(ip=ip)

    msg_log = {
        "action_name": "获取进程信息",
        "ip": ip, "process_name": process_name,
        "status_code": None,
        "user": request.user.user_name,
        "msg": process_info_list.get('data', "刷新信息失败")
    }
    if process_info_list["status_code"] == False:
        # 记录操作日志 失败原因
        msg_log["status_code"] = False
        write_msg_to_log_and_db_task(**msg_log)
        return JsonResponse(msg_log)

    del process_info_list["status_code"]

    # 更新进程列表状态
    supervisor_processlist_status_update_task(ip=ip, process_list=process_info_list["data"])
    # 从列表循环取到 当前process_name 进程的信息
    msg = {"data": value for value in process_info_list["data"] if value["name"] == process_name}
    msg["status_code"] = True
    # 记录操作日志
    msg_log["status_code"] = True
    msg_log["msg"] = "成功"
    write_msg_to_log_and_db_task(**msg_log)
    msg["data"]["ip"] = ip

    supv_host_obj = SupervisorHost.objects.filter(ip=ip).first()
    msg["data"]["主机"] = supv_host_obj.hostname

    return JsonResponse(msg)


@login_required
def refresh_host_all_process(request):
    """
    刷新一台主机所有进程信息
        :param request: ip
        :return:
    """
    ip = request.GET.get('ip', None)
    if not ip:
        msg = {"status_code": False, "data": f"缺少参数:ip"}
        return JsonResponse(msg)

    # 判断数据库中是否存在此对象
    super_host_obj = SupervisorHost.objects.filter(ip=ip, )
    if not super_host_obj.exists():
        data = {"status_code": False, "msg": f"{ip}对象不存在"}
        return JsonResponse(data)

    super_model_obj = Supervisor_Process.objects.filter(ip=ip, )
    if super_model_obj.exists():
        # 删除历史信息
        super_model_obj.delete()

    # 通过api获取信息
    process_info_list = Supervisor_Process_Managet_Class().get_process_info_list(ip=ip)

    msg_log = {
        "action_name": "刷新进程信息",
        "ip": ip,
        "process_name": None,
        "status_code": None,
        "user": request.user.user_name,
        "msg": None
    }
    if process_info_list["status_code"] == False:
        # 记录操作日志 失败原因
        msg_log["status_code"] = False
        msg_log["msg"] = "刷新失败"
        write_msg_to_log_and_db_task(**msg_log)
        return JsonResponse(msg_log)

    del process_info_list["status_code"]

    # 更新进程列表状态
    supervisor_processlist_status_update_task(ip=ip, process_list=process_info_list["data"])
    # 从列表循环取到 当前process_name 进程的信息
    msg = {"status_code": True, "data": f"刷新主机: {ip}进程信息成功"}
    return JsonResponse(msg)


@login_required
def refresh_allhost_allprocess(request):
    """
    刷新所有主机所有进程
        :param request:
        :return:
    """
    #  获取ip列表
    super_host_obj = SupervisorHost.objects.values_list("ip")
    # 删除历史信息
    Supervisor_Process.objects.filter(ip__in=super_host_obj).delete()

    # 通过api获取信息
    msg = {"status_code": True, }
    suc_ip = []
    fail_ip = []
    for ip in super_host_obj:
        ip = ip[0]
        process_info_list = Supervisor_Process_Managet_Class().get_process_info_list(ip=ip)

        if process_info_list["status_code"] == False:
            # 获取信息失败,记录日志跳过循环
            logger.warning(f"刷新{ip[0]}进程信息失败")
            fail_ip.append(ip)
            continue
        # 更新状态到数据库中
        supervisor_processlist_status_update_task(ip=ip, process_list=process_info_list["data"])
        suc_ip.append(ip)
    msg["suc_refresh_host"] = suc_ip
    msg["fail_refresh_host"] = fail_ip
    return JsonResponse(msg)


class Add_Supervisor_Host_View(LoginRequiredMixin, CreateView):
    model = SupervisorHost
    fields = ("hostname", "ip", "port")
    success_url = reverse_lazy("supervisor_list")
    template_name = 'supervisor_dj/supervisor_add_host.html'
